/**
 * Copyright (C), 2022-2025, www.bosssof.com.cn
 * @FileName RoleApi.java
 * @Author Administrator
 * @Date 2022-9-28  17:26
 * @Description 文件定义了角色的管理接口，包括角色增 删 改查 以及角色分配资源
 * History:
 * <author> Administrator
 * <time> 2022-9-28  17:26
 * <version> 1.0.0
 * <desc> 文件定义了角色的管理接口，包括角色增 删 改查 以及角色分配资源
 */
package com.sd365.permission.centre.api;

import com.sd365.common.core.common.api.CommonPage;
import com.sd365.permission.centre.entity.Node;
import com.sd365.permission.centre.entity.Resource;
import com.sd365.permission.centre.entity.Role;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.query.RoleQuery;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.pojo.vo.RoleCompanyVO;
import com.sd365.permission.centre.pojo.vo.RoleVO;
import com.sd365.permission.centre.pojo.vo.UserVO;
import io.swagger.annotations.*;
import org.checkerframework.checker.units.qual.A;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * @Class RoleApi
 * @Description RoleController层接口。
 * <br>主要方法为 角色分配资源（assignResource）和角色分配用户（assignUser）
 * <br>其他方法较为常规主要是针对角色的增删改查
 * @Author Administrator
 * @Date 2022-9-28  17:26
 * @version 1.0.0
 */
@CrossOrigin
@Api(tags = "角色管理 ", value = "/permission/centre/v1/role")
@RequestMapping(value = "/permission/centre/v1/role")
@Validated
public interface RoleApi {
    /**
     * 在系统启动时候将初始化角色和资源的关系，主要为网关鉴权服务
     * abel.zhan 2023-04-20 修改 getMapping为 putMapping
     * @param: 不同的角色初始化不同的资源到内存
     * @return:  成功则true 否则false
     */
    @ApiOperation(tags = "调用接口初始化角色和资源关系", value = "")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    }
    )
    @PutMapping(value = "/initRoleReourceRedis")
    Boolean initRoleResourceRedis(@ApiParam(name = "role",type = "Role",required = true) @NotNull Role role);

    /**
     * 为角色分配资源 支持选择多个角色统一分配资源
     * @param: 对象包含角色id列表和资源列表 为必须填写
     * @return: 成功则true 否则false 异常则被全局统一异常捕获
     */
    @ApiOperation(tags = "为多角色分配多资源", value = "")
    @ApiImplicitParam(name = "roleResourceDTO",value = "角色对应资源对象",required = true,dataType = "RoleResourceDTO",paramType = "body")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    }
    )
    @PostMapping(value = "/assignResource")
    @ResponseBody
    Boolean assignResource(@NotNull @Valid @RequestBody RoleResourceDTO roleResourceDTO);

    /**
     * 为角色分配用户，因为涉及多条插入记得启动事务管理，如果您的实现方式是
     * 直接单条依据批量插入那请忽略事务
     * @Author: Administrator
     * @DATE: 2022-9-28  17:51
     * @param:  当前勾选的用户以及从用户查询对话框多选的用户
     * @return: 插入成功则true 失败则false 异常则被全局统一异常捕获
     */
    @ApiOperation(tags = "为多角色分配多用户", value = "")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    }
    )
    @PostMapping(value = "/assignUser")
    @ResponseBody
    Boolean assignUser(@NotNull @Valid @RequestBody UserRoleDTO userRoleDTO);

    /**
     * 查看角色的通过角色id获取该角色拥有的资源,角色界面未发起对该方法考虑非在角色管理模块
     * 使用，所以培训项目不要求实现改方法 请忽略该方法的实现
     * @param roleQuery 支持传入id和名字 建议参数和名字保持一致有待改进
     * @return Node
     */
    @ApiOperation(tags = "根据roleId查询角色分配的资源", value = "")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    })
    @PostMapping(value = "/resource")
    @ResponseBody
    @Deprecated
    List<Node> doQueryResourceByRoleId(@NotNull @RequestBody RoleQuery roleQuery);

    /**
     * 通过角色id获取该角色拥有的资源 ，数据默认为该租户
     */
    @ApiOperation(tags = "查询角色表中包含的公司", value = "")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    })
    @GetMapping(value = "/selectCompany")
    @ResponseBody
    List<Node> selectCompany();

    /**
     * 验证角色名字是否已经存在
     * 若存在，返回 true ;若不存在，返回 false
     * @param roleDTO 角色名
     * @return Node
     */
    @ApiOperation(tags = "验证角色是否重复", value = "")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    })
    @PostMapping(value = "/haveName")
    @ResponseBody
    @Deprecated // TODO 检查前端并未发现该接口调用，该接口目前为废弃，后续将重构启用该接口
    boolean haveRole(@NotNull @RequestBody RoleDTO roleDTO);

    /**
     *  增加角色,允许不带资源列表，后续用户通过assignRoleResource接口增加资源
     * @param: 角色DTO
     * @return: 成功则true CommonResponse 应答码和消息统一参考基础框架
     */
    @ApiOperation(tags = "增加角色", value = "")
    @ApiImplicitParam(name = "roleDTO",value = "增加的角色",required = true,dataType = "RoleDTO",paramType = "body")
    @ApiResponses({
            @ApiResponse(code = 0,message = "请求成功"),
            @ApiResponse(code=-1,message = "没有更新记录,非0码则代表失败")
    })
    @PostMapping(value = "")
    @ResponseBody
    Boolean add(@NotNull @Valid @RequestBody  RoleDTO roleDTO);

    /**
     *  删除角色，注意要删除角色对应资源
     * @param id 角色id
     * @param version  角色记录版本
     * @return true成功 false失败 如果内部删除主表和明细表失败则引发异常
     */
    @ApiOperation(tags = "删除角色", value = "")
    @ApiImplicitParams({@ApiImplicitParam(name = "id",required =true,dataType = "Long",paramType = "query"),
            @ApiImplicitParam(name = "version",required =true,dataType = "Long",paramType = "query")}
    )
    @DeleteMapping(value = "")
    @ResponseBody
    Boolean remove(@ApiParam(value = "当前行id", required = true) @NotNull @RequestParam("id") Long id,
                   @ApiParam(value = "当前行版本", required = true)@NotNull @RequestParam("version") Long version);

    /**
     * 批量删除角色，注意要记得删除角色关联的资源
     * @param: roleDTOS 角色id 如果传送id数组更好，建议培训阶段执行的项目的时候改进
     * @return: 成功则true 否则false 如果批量中一条失败则引发事务回滚
     */
    @ApiOperation(tags = "批量删除角色", value = "")
    @ApiImplicitParams({@ApiImplicitParam(name = "roleDTOS",required =true,dataType = "RoleDTO",paramType = "body")}
    )
    @DeleteMapping(value = "/batch")
    @ResponseBody
    Boolean batchRemove(@NotNull @Valid @RequestBody  RoleDTO[] roleDTOS);

    /**
     * 修改角色的数据，依据前端界面改修改只支持角色的信息不包括角色所有用的资源
     * @param: 角色基本信息 注意必须填字段
     * @return: 成功 true 失败 false 如果触发重复的角色编号等规则可能引发异常全局异常捕获
     */
    @ApiOperation(tags = "修改角色", value = "")
    @ApiImplicitParam(name = "roleDTO",value = "角色对象",required = true,dataType = "RoleDTO",paramType = "body")
    @PutMapping(value = "")
    @ResponseBody
    Boolean modify(@NotNull @Valid @RequestBody RoleDTO roleDTO);

    /**
     * 执行数据的查询然后在展示在拷贝对话框，请不要被方法名所迷惑
     * @param: 所选择的拷贝的角色id
     * @return: 依据id返回 角色DTO对象
     */
    @ApiOperation(tags = "拷贝角色", value = "/copy")
    @PostMapping(value = "/copy")
    @ResponseBody
    RoleDTO copy(@ApiParam(name = "id",type="String",required = true) @NotNull Long id);

    /**
     * @
     *  系统框架GlobalControllerResolver 类分析 参数是否 BaseQuery 类型 ，如果是则 拦截调用
     *  <br> PageHelper 分页方法， 并且将返回的page对象放入TheadLocal ，方法返回参数被 ResponseBodyAware拦截
     *  <br> 其判断 返回值的类型 如果是属于分页的请求则 自动将 List<RoleVO> 装入CommonPage
     *  <br> 并且构建统一应答回去 以上改进优化了 请求和应答的方法的编写
     * @param:  角色管理查询区域传入的对象，因为继承自BaseQuery所以自带了查询分页参数
     * @return: 当前页面的角色数据，如果需要希望一页带回数据则可以在查询参数设置PageSize为大数
     */
    @ApiOperation(tags = "查询角色", value = "")
    @ApiImplicitParam(name = "roleQuery",value = "角色查询参数",required = true,dataType = "roleQuery",paramType = "query")
    @GetMapping(value = "")
    @ResponseBody
    CommonPage<RoleDTO> commonQuery(@NotNull RoleQuery roleQuery);

    /**
     *  在ui进行角色绑定相关用户的时候，需要弹出dialog显示用户数据，该方法返回用户列表
     *  可以在RoleService调用UserService或者dao完成
     *  abel.zhan 2023-04-23 重构List<UserVO> 为 CommonPage<UserDTO>
     * @param userQuery 用户查询条件
     * @return 用户列表
     */
    @ApiOperation(tags = "查询用户", value = "")
    @ApiImplicitParam(name = "userQuery",value = "用户查询参数",required = true,dataType = "UserQuery",paramType = "query")
    @GetMapping(value = "/commonQueryUser")
    @ResponseBody
    CommonPage<UserDTO> commonQueryUser(@NotNull UserQuery userQuery);
    /**
     * 通过角色id返回角色对象
     * @param: 角色id
     * @return: 角色VO对象用于编辑角色需要展示角色数据调用
     */
    @ApiOperation(tags = "查询角色 BY ID", value = "")
    @ApiImplicitParam(name = "id",value = "角色id",required = true,dataType = "Long",paramType = "path")
    @GetMapping(value = "/{id}")
    @ResponseBody
    RoleVO queryRoleById(@NotNull @PathVariable("id") Long id);
    /**
     * 其他模块使用此方法,此方法存在业务理解缺陷
     * @param: 用户id
     * @return: 用户对象的角色 该方法存在缺陷用户可能有多个角色
     */
    @ApiOperation(tags = "查询用户资源 BY ID", value = "")
    @ApiImplicitParam(name = "id",value = "用户id",required = true,dataType = "Long",paramType = "query")
    @GetMapping(value = "/queryUserResource")
    @ResponseBody
    RoleVO queryUserResource(@NotNull @RequestParam(value = "id", required = true) Long id);

    /**
     * 通过id查询角色公司关系，培训项目不要求实现功能点
     * @param id 公司id
     * @return RoleCompanyVO  公司的角色
     */
    @ApiOperation(tags = "通过id查询角色公司关系", value = "/company")
    @ApiImplicitParam(name = "id",value = "角色id",required = true,dataType = "Long",paramType = "qeury")
    @GetMapping(value = "/company")
    @ResponseBody
    RoleCompanyVO queryRoleCompanyById(@NotNull @RequestParam(value = "id") Long id);

    /**
     * @Description:修改角色公司关系 通过id查询角色公司关系，培训项目不要求实现功能点
     * @param roleCompanyDTO
     * @return Boolean
     */
    @ApiOperation(tags = "修改角色公司关系", value = "/company")
    @ApiImplicitParam(name = "roleCompanyDTO",value = "角色公司对象",required = true,dataType = "RoleCompanyDTO",paramType = "body")
    @PutMapping(value = "/company")
    @ResponseBody
    Boolean modifyRoleCompany(@NotNull @Valid @RequestBody  RoleCompanyDTO roleCompanyDTO);


}
